package com.mega.common.generator;

import com.baomidou.mybatisplus.annotation.DbType;
import com.mega.common.generator.config.*;
import com.mega.common.generator.config.po.TableInfo;
import com.mega.common.generator.config.rules.DateType;
import com.mega.common.generator.config.rules.NamingStrategy;
import lombok.Builder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Mybatis-Plus代码生成工具
 *
 * @author Eric
 */
@Builder
@Slf4j
public class CodeGenerator {

    //作者
    public String author;
    //输出目录
    public String outPutDir;
    //表前缀
    public String[] tablePrefix;
    //表名
    public String[] tableName;
    //项目包路径
    public String projectPackage;
    //模块包路径
    public String modulePackage;
    //数据库配置
    public DbType dbType;
    //数据库驱动
    public String dbDriver;
    //数据库用户名
    public String dbUsername;
    //数据库密码
    public String dbPassword;
    //数据库url
    public String dbUrl;

    /**
     * 生成代码
     */
    public void execute() {

        AutoGenerator mpg = new AutoGenerator();

        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        /*
            设置作者名
         */
        gc.setAuthor(author);

        /*
            代码生成器所在路径
         */
        gc.setOutputDir(outPutDir);

        gc.setFileOverride(true);// 是否覆盖同名文件，默认是false
        gc.setActiveRecord(true);// 不需要ActiveRecord特性的请改为false
        gc.setEnableCache(false);// XML 二级缓存
        gc.setBaseResultMap(true);// XML ResultMap
        gc.setBaseColumnList(true);// XML columList
        gc.setSwagger2(true);
        gc.setDateType(DateType.TIME_PACK);

        /* 自定义文件命名，注意 %s 会自动填充表实体属性！ */
        //gc.setEntityName("%sEntity");
        gc.setEntityName(null);
        gc.setControllerName("%sController");
        gc.setServiceName("%sService");
        gc.setServiceImplName("%sServiceImpl");
        gc.setMapperName("%sMapper");
        gc.setXmlName("%sMapper");
        mpg.setGlobalConfig(gc);

        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setDbType(dbType);
        dsc.setDriverName(dbDriver);

        /*
            设置数据库用户名
         */
        dsc.setUsername(dbUsername);

        /*
            设置数据库密码
         */
        dsc.setPassword(dbPassword);

        /*
            设置数据库url
         */
        dsc.setUrl(dbUrl);
        mpg.setDataSource(dsc);

        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setRestControllerStyle(true);
        strategy.setEntityLombokModel(true);
        strategy.setSuperControllerClass("com.mega.common.core.web.controller.MageBaseController");
        strategy.setSuperEntityClass("com.mega.common.core.web.model.entity.MegaBaseEntity");

        /*
            此处可以修改为您的表前缀,如有多个,则后可变形参后追加
         */
        strategy.setTablePrefix(tablePrefix);

        /*
            设置具体的表名
         */
        strategy.setInclude(tableName);

        strategy.setNaming(NamingStrategy.underline_to_camel);// 表名生成策略
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setSuperEntityColumns(new String[]{"ID", "CREATE_BY", "CREATE_TIME", "DEL_FLAG", "UPDATE_BY", "UPDATE_TIME", "VERSION"});
        strategy.setSuperMapperClass(null);

        mpg.setStrategy(strategy);

        // 包配置
        PackageConfig pc = new PackageConfig();

        pc.setParent(projectPackage);

        String packageName = StringUtils.isNotBlank(modulePackage) ? "." + modulePackage : modulePackage;
        pc.setController("controller" + packageName);
        pc.setService("service" + packageName);
        pc.setServiceImpl("service" + packageName + ".impl");
        pc.setMapper("mapper" + packageName);
        pc.setEntity("model.entity" + packageName);
        pc.setDto("model.dto" + packageName);
        pc.setXml("mapper" + packageName);
        mpg.setPackageInfo(pc);

        //模板
        InjectionConfig config = new InjectionConfig() {
            @Override
            public void initMap() {
                Map<String, Object> map = new HashMap<String, Object>();
                this.setMap(map);
            }
        };

        List<FileOutConfig> files = new ArrayList<FileOutConfig>();
        files.add(new FileOutConfig("/templates/controller.java.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                String expand = gc.getOutputDir() + (File.separator + pc.getParent() + "." + pc.getController()).replace(".", File.separator);
                String entityFile = String.format((expand + File.separator + "%s" + ".java"), tableInfo.getControllerName());
                return entityFile;
            }
        });
        files.add(new FileOutConfig("/templates/service.java.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                String expand = gc.getOutputDir() + (File.separator + pc.getParent() + "." + pc.getService()).replace(".", File.separator);
                String entityFile = String.format((expand + File.separator + "I" + "%s" + ".java"), tableInfo.getServiceName());
                return entityFile;
            }
        });
        files.add(new FileOutConfig("/templates/serviceImpl.java.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                String expand = gc.getOutputDir() + (File.separator + pc.getParent() + "." + pc.getServiceImpl()).replace(".", File.separator);
                String entityFile = String.format((expand + File.separator + "%s" + ".java"), tableInfo.getServiceImplName());
                return entityFile;
            }
        });
        files.add(new FileOutConfig("/templates/entity.java.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                String expand = gc.getOutputDir() + (File.separator + pc.getParent() + "." + pc.getEntity()).replace(".", File.separator);
                String entityFile = String.format((expand + File.separator + "%s" + ".java"), tableInfo.getEntityName());
                return entityFile;
            }
        });
        files.add(new FileOutConfig("/templates/mapper.java.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                String expand = gc.getOutputDir() + (File.separator + pc.getParent() + "." + pc.getMapper()).replace(".", File.separator);
                String entityFile = String.format((expand + File.separator + "%s" + ".java"), tableInfo.getMapperName());
                return entityFile;
            }
        });
        files.add(new FileOutConfig("/templates/mapper.xml.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                String expand = gc.getOutputDir() + (File.separator + pc.getParent() + "." + pc.getXml()).replace(".", File.separator);
                String entityFile = String.format((expand + File.separator + "%s" + ".xml"), tableInfo.getXmlName());
                return entityFile;
            }
        });
        files.add(new FileOutConfig("/templates/querydto.java.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                String expand = gc.getOutputDir() + (File.separator + pc.getParent() + "." + pc.getDto()).replace(".", File.separator);
                String entityFile = String.format((expand + File.separator + "%s" + ".java"), tableInfo.getEntityName() + "QueryDTO");
                return entityFile;
            }
        });
        config.setFileOutConfigList(files);
        mpg.setCfg(config);

        TemplateConfig tc = new TemplateConfig();
        tc.setController(null);
        tc.setEntity(null);
        tc.setMapper(null);
        tc.setService(null);
        tc.setServiceImpl(null);
        tc.setXml(null);
        mpg.setTemplate(tc);

        // 执行生成
        mpg.execute();
        log.info("代码生成完成^_^");
    }
}
